const fs = require('fs');
const path = require('path');

module.exports = async function (key, value, timeout, forceRefresh = false) {

  const adapter = saas.adapter.cache;
  if (saas.isEmpty(timeout)) {
    timeout = adapter.common.timeout;
  }
  if (adapter.type === 'file') {
    if (!fs.existsSync(path.join(saas.ROOT_PATH, adapter.common.cachePath))) {
      fs.mkdirSync(path.join(saas.ROOT_PATH, adapter.common.cachePath), {recursive: true});
    }
  }

  //get
  if (saas.isEmpty(value)) {

    if (adapter.type === 'file') {
      const filePath = path.join(saas.ROOT_PATH, adapter.common.cachePath, `${key}.cache`);
      if (!fs.existsSync(filePath)) {
        return null;
      }
      const readFile = saas.promisify(fs.readFile, fs);
      const data = await readFile(filePath, {encoding: 'utf-8'});
      const jsonData = JSON.parse(data);
      if (new Date().getTime() > jsonData.expireTime) {
        return null;
      }
      return jsonData.data;
    } else if (adapter.type === 'redis') {
      const {redis} = saas.app;
      const redisGet = saas.promisify(redis.get, redis);
      const val = await redisGet(key);
      console.log(val);
      if (!saas.isTrueEmpty(val)) {
        const jsonData = JSON.parse(val);
        if (new Date().getTime() > jsonData.expireTime) {
          return null;
        }
        return jsonData.data;
      }else{
        return null;
      }
    }
  } else if (typeof value == 'function') { // if no cache, do function
    if (adapter.type === 'file') {
      const filePath = path.join(saas.ROOT_PATH, adapter.common.cachePath, `${key}.cache`);
      let reloadFlag = forceRefresh;
      let jsonData = {};
      if (!fs.existsSync(filePath)) {
        reloadFlag = true;
      } else {
        const readFile = saas.promisify(fs.readFile, fs);
        const data = await readFile(filePath, {encoding: 'utf-8'});
        jsonData = JSON.parse(data);
        if (new Date().getTime() > jsonData.expireTime) {
          reloadFlag = true;
        }
      }

      if (reloadFlag) {
        const func = await value();
        jsonData = {
          key: key,
          data: func,
          expireTime: new Date().getTime() + timeout
        };
        fs.writeFile(filePath, JSON.stringify(jsonData), err => {
          if (err) {
            console.log(`[saas-cache] ${err}`);
          }
        });
      }
      return jsonData.data;
    } else if (adapter.type === 'redis') {
      const {redis} = saas.app;
      const redisGet = saas.promisify(redis.get, redis);
      const val = await redisGet(key);
      let reloadFlag = forceRefresh;
      let jsonData;
      if (!saas.isTrueEmpty(val)) {
        jsonData = JSON.parse(val);
        if (new Date().getTime() > jsonData.expireTime) {
          reloadFlag = true;
        }
      } else {
        reloadFlag = true;
      }

      if (reloadFlag) {
        const func = await value();
        jsonData = {
          key: key,
          data: func,
          expireTime: new Date().getTime() + timeout
        };
        redis.set(key, JSON.stringify(jsonData), 'PX',timeout,(err) => {
          console.log(`[saas-cache-redis] ${err}`);
        })
      }
      return jsonData.data;
    }
  } else {
    if (adapter.type === 'file') { //set
      const filePath = path.join(saas.ROOT_PATH, adapter.common.cachePath, `${key}.cache`);
      const jsonData = {
        key: key,
        data: value,
        expireTime: new Date().getTime() + timeout
      };
      fs.writeFile(filePath, JSON.stringify(jsonData), function (err) {
        if (err)
          console.log(`[saas-cache] ${err}`);
      });
    } else {
      const {redis} = saas.app;
      const jsonData = {
        key: key,
        data: value,
        expireTime: new Date().getTime() + timeout
      };
      redis.set(key, JSON.stringify(jsonData),'PX',timeout, (err) => {
        console.log(`[saas-cache-redis] ${err}`);
      })
    }
  }
};